'''
Created on 2011-07-08

@author: Mikael
'''

from PyQt4 import Qt 
from PyQt4 import QtCore
from PyQt4.QtCore import QModelIndex
from Model.GenericNode import GenericNode
#from PyQt4.uic.Compiler.qtproxies import QtGui
import PyQt4
from PyQt4.uic.Compiler.qtproxies import QtGui
from Model.NodeFolder import NodeFolder


class NodeMimeData(QtCore.QMimeData):
    
    def __init__(self, GenericNodeList=[], QModelIndexParents = [], indicesInParent = []):
        '''
        '''
        QtCore.QMimeData.__init__(self)
        self.mGenericNodeList = GenericNodeList
        self.mParents = QModelIndexParents;
        self.mIndicesInParent = indicesInParent
        
        text = ""
        for node in GenericNodeList:
            text += node.getText(0) + "\n"
        self.setText(text);
        self.setData('text/xml', 'mimeData')
        
    def getGenericNodeList(self):
        return self.mGenericNodeList


class TreeModel(Qt.QAbstractItemModel):
    '''
    classdocs
    '''

    def __init__(self, headers=[], rootNodes=[]):
        '''
        Constructore: 
        Headers = String list for headers titles
        rootNodes = tree root nodes
        '''
        Qt.QAbstractItemModel.__init__(self)
        self.mRootNodes = rootNodes;
        self.mHeaders = headers
        
        
        


    def columnCount(self, parent=Qt.QModelIndex()):
        '''
        Get the tree column count
        '''
        
        ll = len(self.mHeaders)
        
        return ll;
    
    
    def data(self, QModelIndex, role=PyQt4.QtCore.Qt.DisplayRole):
        '''
        Get the data of the node from a given index
        '''
        
        if not QModelIndex.isValid():
            return None
        
        if role == PyQt4.QtCore.Qt.DecorationRole and QModelIndex.column() == 0:
            return QModelIndex.internalPointer().getIcon()
        
        if role != PyQt4.QtCore.Qt.DisplayRole:
            return None
        
        node = QModelIndex.internalPointer()  # self.getNodeFromIdx(QModelIndex)
        
        val = node.getData(QModelIndex.column())
        
        return val
        
    def flags(self, QModelIndex):
        '''
        Set the window flags
        '''
        
        if not QModelIndex.isValid():
            return QtCore.Qt.NoItemFlags
        return  QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled;
    
    def mimeData(self, list_of_QModelIndex):
        
        nodeList = []
        qmodelIndexParentList = []
        indicesInParent =  []
        for nodeIdx in list_of_QModelIndex:
            
            node = self.getNodeFromIdx(nodeIdx)
            nodeList.append(node)
            qmodelIndexParentList.append(self.parent(nodeIdx))
            indicesInParent.append(node.getChildIndexInParentNode())
        
        mimeData =  NodeMimeData(nodeList, qmodelIndexParentList, indicesInParent);
        
        #self.dropMimeData(QMimeData, Qt_DropAction, int, int, QModelIndex)
        
        return mimeData
    
    def dropMimeData(self, mimeData, Qt_DropAction, row, column, parent):
        #QtCore.Qt.CopyAction | QtCore.Qt.MoveAction
        
        
        
        if Qt_DropAction ==  QtCore.Qt.MoveAction:
            '''
            '''
            if isinstance(mimeData, NodeMimeData):
                rowToInsert = row
                node = self.getNodeFromIdx(parent)
                if not isinstance(node, NodeFolder):
                    rowToInsert = node.getChildIndexInParentNode()
                    parentIdx = self.parent(parent)
                    parent = parentIdx
                    
                    
                idx = 0
                
                movedNodeList = mimeData.getGenericNodeList()
                currIdx = 0
                for movedNode in movedNodeList:
                    parentIdx = mimeData.mParents[currIdx]
                    indexInParent = mimeData.mIndicesInParent[currIdx]
                    
                    self.beginRemoveRows(parentIdx, indexInParent, indexInParent)
                    movedNodeParent = movedNode.mParent
                    movedNodeParent.removeChildNode(movedNode);
                    self.endRemoveRows()
                    
                    self.insertRow(rowToInsert, parent, movedNode)
                    
                    currIdx += 1
                
                return 1;
        
        return 0
        
    
    def mimeTypes(self):
        return ['text/xml']
    
    '''def dropMimeData(self, data, action, row, column, parent):
        print 'dropMimeData %s %s %s %s' % (data.data('text/xml'), action, row, parent) 
        return True'''
        


    def getNodeFromIdx(self, QModelIndex):
        '''
        Get a given node
        '''       
        if QModelIndex.isValid():
            item = QModelIndex.internalPointer()
            if item != None:
                return item
        else:
            return self.mRootNodes[0]
        
        
    
        
    def headerData(self, int, Qt_Orientation, role=PyQt4.QtCore.Qt.DisplayRole):
        '''
        Set the header data
        '''
        if Qt_Orientation == QtCore.Qt.Horizontal and role == PyQt4.QtCore.Qt.DisplayRole:
            return self.mHeaders[int]
        
        return None
            
        

    def index(self, row, column, QModelIndex):
        '''
        Get the node at a given idex in the subnode list of a parent node
        GenericNode: The parent node
        '''
        if not self.hasIndex(row, column, QModelIndex):
            return QtCore.QModelIndex()
        
        parentNode = None
        
        if not QModelIndex.isValid():
            parentNode = self.mRootNodes[0]
        else:
            parentNode = QModelIndex.internalPointer()
        
        nodeAtIdx = parentNode.getChildNodeAt(row)
        
        if nodeAtIdx != None:
            return self.createIndex(row, column, nodeAtIdx)
        else:
            return QtCore.QModelIndex()

    def parent(self, QModelIndex):
        '''
        Returns the parent of the model item with the given index. If the model has no parent, an invalid QModelIndex is returned.

        A common convention used in models that expose tree data structures is that only items in the first column have children. 
        For that case, when reimplementing this function in a subclass the column of the returned QModelIndex would be 0.

        When reimplementing this function in a subclass, be careful to avoid calling QModelIndex member functions, 
        such as QModelIndex::parent(), since indexes belonging to your model will simply call your implementation, l
        eading to infinite recursion.
        '''

        #for line in traceback.format_stack():
        #    print(line.strip())
        
        
        #if not QModelIndex.isValid():
        #    print("parent:IndexNotValid")
        #    return QModelIndex
        
        childNode = QModelIndex.internalPointer()
        parentNode = childNode.mParent

        if parentNode is self.mRootNodes[0]:
            return QtCore.QModelIndex()

        if self.mRootNodes[0] == parentNode:
            return QtCore.QModelIndex()
        
        return self.createIndex(parentNode.getChildIndexInParentNode(), 0, parentNode)
    
    def setRowToInsert(self, rows=[]):
        self.mRowsToInsert = rows

    def insertRows(self, position, rows, QModelIndex):
        success = 1
        parentNode = QModelIndex.internalPointer()
        
        self.beginInsertRows()
        for n in self.mRowsToInsert:
            parentNode.addChildNode(n)
        self.endInsertRows()

        self.insertRow

        return success
    
    def insertRow(self, idx, QModelIndex, children):
        
        parentNode = QModelIndex.internalPointer()
        
        self.beginInsertRows(QModelIndex, idx, idx)
        success = parentNode.insertChildenNodeIdx(children, idx)
        self.endInsertRows()
        
        return success

    def removeRow(self, rowIdxInParent, parent=QModelIndex()):
        parentNode = self.getNodeFromIdx(parent)

        self.beginRemoveRows(parent, rowIdxInParent, rowIdxInParent)
        success = parentNode.removeChildNodebyIdx(rowIdxInParent)
        self.endRemoveRows()

        return success

    
    def rowCount(self, QModelIndex):
        '''
        Returns the number of rows under the given parent. When the parent is valid it means that rowCount is returning the number of children of parent.
        Note: When implementing a table based model, rowCount() should return 0 when the parent is valid.
        '''
        
        parentNode = self.getNodeFromIdx(QModelIndex)
        
        count = parentNode.getChildCount()
        return count

    def updateChange(self, GenericNode):

        idx = GenericNode.getChildIndexInParentNode()
        start = self.createIndex(idx, 0, GenericNode)
        end = self.createIndex(idx, 0, GenericNode)
        
        self.dataChanged.emit(start, end)
        
        #self.supportedDropActions()
        
    def supportedDropActions(self): 
        return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction  
    
    


    

    #def setData(self, QModelIndex, QVariant, role=PyQt4.QtCore.Qt.EditRole):
        #    if role != QtCore.Qt.Qt_EditRole:
        #        return 0
        #    
        #     node = self.getNodeFromIdx(QModelIndex)
        #     resultBool = node.setColumnData(QModelIndex.column(), QVariant)
        # #    
        #     return resultBool
 
    # def setHeaderData(self, section, orientation, QVariant, role=PyQt4.QtCore.Qt.EditRole):
        #if role != PyQt4.QtCore.Qt.EditRole or orientation != QtCore.Qt.Horizontal:
        #     return 0
        
        #result = self.mRootNodes[0].setColumnData(section, QVariant)
        
        #if result:
            #self.headerDataChanged()
        
        #return 1
